/*
 * @Description: Axios 实例配置与拦截器
 * @Version: 2.0
 * @Autor: wangmeng
 * @Date: 2021-08-03 11:13:38
 * @LastEditors: wamgmeng
 * @LastEditTime: 2024-01-18 15:11:04
 */
/* eslint-disable no-param-reassign */
import type {
    AxiosInstance,
    AxiosRequestConfig,
    AxiosResponse,
    AxiosError,
    InternalAxiosRequestConfig,
} from "axios";
import axios from "axios";
import qs from "qs";
import type { ResponseType } from "./global.type";

// 响应状态码枚举
enum ResponseStatus {
    SUCCESS = 0,
    SUCCESS_1 = 200,
    REDIRECT = 302,
    FORBIDDEN = 400003,
}

// 请求超时时间（3000秒）
const REQUEST_TIMEOUT = 3000000;

/**
 * 处理重定向逻辑
 */
const handleRedirect = (result: string): void => {
    const root = result.includes("http://") || result.includes("https://") ? "" : "http://";

    setTimeout(() => {
        if (result.includes("serverName")) {
            window.location.href = `${root}${result}`;
        } else {
            const encodedUrl = encodeURIComponent(window.btoa(window.location.href));
            window.location.href = `${root}${result}?serverName=${encodedUrl}`;
        }
    }, 300);
};

/**
 * 创建并配置 JSON 格式的 Axios 实例
 */
const createJsonHttp = (): AxiosInstance => {
    const instance = axios.create({
        timeout: REQUEST_TIMEOUT,
        transformRequest: [
            (data: unknown): string => {
                return JSON.stringify(data);
            },
        ],
    });

    // 请求拦截器
    instance.interceptors.request.use(
        (config: InternalAxiosRequestConfig): InternalAxiosRequestConfig => {
            const headers: any = config.headers as any;
            if (headers && typeof headers.set === "function") {
                headers.set("Content-Type", "application/json");
            } else {
                config.headers = (config.headers ?? {}) as any;
                (config.headers as any)["Content-Type"] = "application/json";
            }
            return config;
        },
        (error: AxiosError): Promise<AxiosError> => {
            return Promise.reject(error);
        }
    );

    // 响应拦截器
    instance.interceptors.response.use(
        <T>(response: AxiosResponse<ResponseType<T>>): Promise<T> | Promise<never> => {
            if (response.status < 400) {
                const { data } = response;
                const statusCode = data.code ?? data.status;

                // 处理重定向
                if (statusCode === ResponseStatus.REDIRECT) {
                    const redirectUrl = data.result || data.message;
                    if (typeof redirectUrl === "string") {
                        handleRedirect(redirectUrl);
                    }
                    return Promise.reject(new Error("Redirecting..."));
                }

                // 处理成功响应 - 返回 data 字段（已解包第一层 ResponseType）
                if (
                    statusCode === ResponseStatus.SUCCESS ||
                    statusCode === ResponseStatus.SUCCESS_1 ||
                    statusCode === ResponseStatus.FORBIDDEN
                ) {
                    if (
                        statusCode === ResponseStatus.SUCCESS ||
                        statusCode === ResponseStatus.SUCCESS_1
                    ) {
                        return Promise.resolve(data.data);
                    }
                    return Promise.reject(new Error(data.message || "Request failed"));
                }

                // 其他状态码视为错误 - 直接 reject 完整的 ResponseType
                return Promise.reject(data);
            }

            return Promise.reject(new Error(`HTTP Error: ${response.status}`));
        },
        (error: AxiosError): Promise<AxiosError> => {
            return Promise.reject(error);
        }
    );

    return instance;
};

/**
 * 创建并配置 FormData 格式的 Axios 实例
 */
const createFormDataHttp = (): AxiosInstance => {
    const instance = axios.create({
        timeout: REQUEST_TIMEOUT,
        transformRequest: [
            (data: unknown): string => {
                return qs.stringify(data);
            },
        ],
    });

    // 请求拦截器
    instance.interceptors.request.use(
        (config: InternalAxiosRequestConfig): InternalAxiosRequestConfig => {
            const headers: any = config.headers as any;
            if (headers && typeof headers.set === "function") {
                headers.set("Content-Type", "application/x-www-form-urlencoded");
            } else {
                config.headers = (config.headers ?? {}) as any;
                (config.headers as any)["Content-Type"] = "application/x-www-form-urlencoded";
            }
            return config;
        },
        (error: AxiosError): Promise<AxiosError> => {
            return Promise.reject(error);
        }
    );

    // 响应拦截器
    instance.interceptors.response.use(
        <T>(response: AxiosResponse<ResponseType<T>>): Promise<T> | Promise<never> => {
            if (response.status < 400) {
                const { data } = response;
                const statusCode = data.code ?? data.status;

                // 处理重定向
                if (statusCode === ResponseStatus.REDIRECT) {
                    const redirectUrl = data.result || data.message;
                    if (typeof redirectUrl === "string") {
                        handleRedirect(redirectUrl);
                    }
                    return Promise.reject(new Error("Redirecting..."));
                }

                // 处理成功响应 - 返回 data 字段（已解包第一层 ResponseType）
                if (
                    statusCode === ResponseStatus.SUCCESS ||
                    statusCode === ResponseStatus.SUCCESS_1 ||
                    statusCode === ResponseStatus.FORBIDDEN
                ) {
                    if (
                        statusCode === ResponseStatus.SUCCESS ||
                        statusCode === ResponseStatus.SUCCESS_1
                    ) {
                        return Promise.resolve(data.data);
                    }
                    return Promise.reject(new Error(data.message || "Request failed"));
                }

                // 其他状态码视为错误 - 直接 reject 完整的 ResponseType
                return Promise.reject(data);
            }

            return Promise.reject(new Error(`HTTP Error: ${response.status}`));
        },
        (error: AxiosError): Promise<AxiosError> => {
            return Promise.reject(error);
        }
    );

    return instance;
};

// 创建实例
const http = createJsonHttp();
const formDataHttp = createFormDataHttp();

export { http, formDataHttp };
export type { AxiosInstance, AxiosRequestConfig, AxiosResponse };
